import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from datetime import timedelta
from hhpy.plotting import animplot
# set pyplot rcParams
plt.rcParams['figure.figsize'] = (10,4)
# first let's make some data
df = pd.DataFrame({'x':np.linspace(0,99,1000)})
# start with a sine wave
df['y'] = np.sin(df['x'])*10
# timestamp
df['t'] = pd.to_datetime('2018-01-01')
# init list of dfs
dfs = [df]
for _i in range(30):
_df = dfs[_i].copy()
# make the wave increase and shift
_df['y'] = np.sin(_df['x']-_i)*10*(1+_i/100)
# shift date by 1
_df['t'] += timedelta(days=1)
dfs.append(_df)
del _df
df = pd.concat(dfs,ignore_index=True,sort=False)
del dfs
a simple plot can be generated by just calling the function with the data/x/y/z format
animplot(data=df,x='x',y='y',t='t',t_format='%Y-%m-%d')
the parameter "mode" controls which object is returned. It can be set inside hhpy.plotting.rcParams
# matplotlib FuncAnimation object (can be saved with .save('FILENAME.mp4'))
print(animplot(data=df,x='x',y='y',t='t',t_format='%Y-%m-%d',mode='matplotlib'))
# HTML5 Movie
animplot(data=df,x='x',y='y',t='t',t_format='%Y-%m-%d',mode='html')
# Interactive JavaScript Widget (default)
animplot(data=df,x='x',y='y',t='t',t_format='%Y-%m-%d',mode='jshtml')
kws are passed to pyplot.plot()
animplot(data=df,x='x',y='y',t='t',t_format='%Y-%m-%d',marker='o',ls='None',markerfacecolor='None',markeredgecolor='blue')
a more complex plot can be generated by first drawing the figure, setting up the lines and passing them to animplot as a list of dictionaries
# calculate diff to plot on second subplot
df['y_diff'] = df['y'].diff()
# init list of dictionaries to be passed to animplot
lines = [{},{}]
fig, ax = plt.subplots(nrows=2,figsize=(12,9))
for _y in range(-10,11,5):
ax[0].axhline(_y,ls=':',color='k',alpha=.5)
ax[1].axhline(_y,ls=':',color='k',alpha=.5)
# linit lines
lines[0]['line'] = ax[0].plot([],[],label='y')[0]
lines[1]['line'] = ax[1].plot([],[],label='y_diff')[0]
# it is recommended to specify the axis for each line (if not it will try to infer)
lines[0]['ax'] = ax[0]
lines[1]['ax'] = ax[1]
# config
lines[0]['y'] = 'y'
lines[1]['y'] = 'y_diff'
# plot options - for legends it is a good idea to specify a position because 'best' tends to change over time
ax[0].legend(loc='upper right')
ax[1].legend(loc='upper right')
# call animplot, shared data doesn't have to be speficied by line
animplot(lines=lines,data=df,x='x',t='t',t_format='%Y-%m-%d',fig=fig,ax=ax)
by default x and y limits are auto detected, if you don't want that you can set them by Hand.
You can either pass them with x_lim=...,y_lim=... (shared across subplots)
or set them beforehand and call the function with xlim=False, ylim=False
# due to the init as empty lines the plot does not have proper limits
ax[0].set_ylim([-15,15])
ax[1].set_ylim([-2,2])
# call animplot with y_lim = False
animplot(lines=lines,data=df,x='x',t='t',fig=fig,ax=ax,ylim=False)